home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / program / funnel.zoo / sources / parser.c < prev    next >
C/C++ Source or Header  |  1993-04-11  |  48KB  |  1,290 lines

  1. /*##############################################################################
  2.  
  3. FUNNNELWEB COPYRIGHT
  4. ====================
  5. FunnelWeb is a literate-programming macro preprocessor.
  6.  
  7. Copyright (C) 1992 Ross N. Williams.
  8.  
  9.    Ross N. Williams
  10.    ross@spam.adelaide.edu.au
  11.    16 Lerwick Avenue, Hazelwood Park 5066, Australia.
  12.  
  13. This program is free software; you can redistribute it and/or modify
  14. it under the terms of Version 2 of the GNU General Public License as
  15. published by the Free Software Foundation.
  16.  
  17. This program is distributed WITHOUT ANY WARRANTY; without even the implied
  18. warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  19. See Version 2 of the GNU General Public License for more details.
  20.  
  21. You should have received a copy of Version 2 of the GNU General Public
  22. License along with this program. If not, you can FTP the license from
  23. prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
  24. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25.  
  26. Section 2a of the license requires that all changes to this file be
  27. recorded prominently in this file. Please record all changes here.
  28.  
  29. Programmers:
  30.    RNW  Ross N. Williams  ross@spam.adelaide.edu.au
  31.  
  32. Changes:
  33.    07-May-1992  RNW  Program prepared for release under GNU GPL V2.
  34.  
  35. ##############################################################################*/
  36.  
  37.  
  38. /******************************************************************************/
  39. /*                                    PARSER.C                                */
  40. /******************************************************************************/
  41.  
  42. #include <setjmp.h>
  43. #include "style.h"
  44.  
  45. #include "as.h"
  46. #include "data.h"
  47. #include "lister.h"
  48. #include "machin.h"
  49. #include "mapper.h"
  50. #include "memory.h"
  51. #include "misc.h"
  52. #include "parser.h"
  53. #include "section.h"
  54. #include "table.h"
  55.  
  56. /******************************************************************************/
  57.  
  58. #define DUMMYINT 0                 /* It doesn't matter what this value is!!! */
  59. #define TKPS &(p_tk->tk_ps)        /* A commonly used construct.              */
  60.  
  61. /******************************************************************************/
  62.  
  63. /* The following variables look after sections. */
  64. LOCVAR sn_t     last_sn;   /* Hierarchical section number of last section.    */
  65. LOCVAR ps_t     pssection; /* Position of last section.                       */
  66. LOCVAR p_dc_t   p_secdc;   /* Pointer to current section document component.  */
  67. LOCVAR tk_t    *p_tk;      /* Pointer to the current token (a structure).     */
  68. LOCVAR ulong    sequence;  /* Current sequence number.                        */
  69. LOCVAR jmp_buf  jmp_pos;   /* Setjmp() position of main parsing loop.         */
  70.  
  71. /******************************************************************************/
  72. /*                             Comparison Functions                           */
  73. /******************************************************************************/
  74.  
  75. LOCAL sign cm_name P_((name_t *,name_t *));
  76. LOCAL sign cm_name(name1,name2)
  77. /* Compares two names and returns:               */
  78. /*    -1 if name1 < name2                        */
  79. /*     0 if name1 = name2                        */
  80. /*     1 if name1 > name2                        */
  81. /* Provides a full ordering on the set of names. */
  82. name_t *name1;
  83. name_t *name2;
  84. {
  85.  return signof(strcmp(&(*name1)[0],&(*name2)[0]));
  86. }
  87.  
  88. /******************************************************************************/
  89.  
  90. LOCAL sign eq_txst P_((p_scls_t,char *));
  91. LOCAL sign eq_txst(p_scls,p_str)
  92. /* The first argument is a list of text scraps.             */
  93. /* The second argument is an ordinary string.               */
  94. /* Returns TRUE iff the two are identical. Otherwise FALSE. */
  95. p_scls_t  p_scls;
  96. char     *p_str;
  97. {
  98.  /* To compare the scrap list with the string, we run through the scrap list */
  99.  /* comparing the bytes its scraps yield progressively with the string.      */
  100.  /* The two scanning groups are (p_scls,p_sc,p_ch) and p_str.                */
  101.  sc_t *p_sc;
  102.  
  103.  ls_fir(p_scls);
  104.  ls_nxt(p_scls,PPV &p_sc);
  105.  while (p_sc!=NULL)
  106.    {
  107.     /* The loop body compares a single scrap pointed to by p_sc. */
  108.     char *p_ch;
  109.     for (p_ch=p_sc->sc_first; p_ch<=p_sc->sc_last; p_ch++)
  110.       {
  111.        if (*p_str==EOS || *p_str != *p_ch) return FALSE;
  112.        p_str++;
  113.       }
  114.     ls_nxt(p_scls,PPV &p_sc);
  115.    }
  116.  return *p_str==EOS;
  117. }
  118.  
  119. /******************************************************************************/
  120. /*                               Parsing Primitives                           */
  121. /******************************************************************************/
  122. /* The following functions provide the basic parsing primitives used by the   */
  123. /* main parsing routines.                                                     */
  124. /******************************************************************************/
  125.  
  126. LOCAL void next_tk P_((bool));
  127. LOCAL void next_tk(iseoferr)
  128. /* This function reads the next token from the token list and places a        */
  129. /* pointer to the token (structure) in the global variable "token".           */
  130. /* The "iseoferr" determines whether a fuss should be made if the next token  */
  131. /* fetched is TK_EOF. If iseoferr==TRUE and the next token is TK_EOF, next_tk */
  132. /* jumps to the main parsing loop.                                            */
  133. bool iseoferr;
  134. {
  135.  ls_nxt(token_list,PPV &p_tk);
  136.  as_cold(p_tk!=NULL,"next_tk: Attempted to read next token at EOF.");
  137.  if (iseoferr && p_tk->tk_kind==TK_EOF)
  138.    {
  139.     lr_err(TKPS,"Ouch! High velocity encounter with end of file.");
  140.     lr_mes(TKPS,"FunnelWeb expected something else when it hit the EOF.");
  141.     longjmp(jmp_pos,DUMMYINT);    /* Jump up to the main parsing loop. */
  142.    }
  143. }
  144.  
  145. /******************************************************************************/
  146.  
  147. LOCAL void recover P_((void));
  148. LOCAL void recover()
  149. /* Parsing functions call this function at points where a syntax error has    */
  150. /* has occurred that it is unlikely that the particular parsing function will */
  151. /* be able to recover from on its own. In these situations, the parser        */
  152. /* resorts to a course grained syntactic error-recovery implemented by this   */
  153. /* function. The goal of the error recovery system is to skip tokens until    */
  154. /* the next major outer-level-syntax structure is encountered. These are:     */
  155. /*    - A new section (@A etc.).                                              */
  156. /*    - A macro definition (@$ or @O).                                        */
  157. /*    - End of file.                                                          */
  158. /* Once one of these three is found, "recover" raises the syntax exception    */
  159. /* which sends control to the main parsing loop which is the correct place    */
  160. /* to deal with a new, major syntactic construct.                             */
  161. {
  162.  lr_mes(TKPS,"Skipping after error to the next major construct...");
  163.  
  164.  /* Skip to one of TK_NSEC,... */
  165.  while (TRUE)
  166.    {
  167.     tk_k_t k = p_tk->tk_kind;
  168.     if (k==TK_NSEC || k==TK_MDEF || k==TK_FDEF || k==TK_EOF) break;
  169.     next_tk(FALSE);
  170.    }
  171.  
  172.  /* Keep the user informed. */
  173.  lr_mes(TKPS,"...skipped to here after the error.");
  174.  
  175.  /* Jump up to the main parsing loop. */
  176.  longjmp(jmp_pos,DUMMYINT);
  177. }
  178.  
  179. /******************************************************************************/
  180.  
  181. LOCAL void genexerr P_((tk_k_t));
  182. LOCAL void genexerr(tk_kind)
  183. /* Genexerr stands for GENerate EXpecting ERRor.                              */
  184. /* Given a token kind, genexerr issues an error saying that the specified     */
  185. /* kind of token was expected. It then invokes recover() for error recovery.  */
  186. tk_k_t tk_kind;
  187. {
  188.  switch (tk_kind)
  189.    {
  190.     /* Note: Not all token kinds are listed here. Only those token kinds that */
  191.     /* are passed to pr_token and check_tk by the main parsing routines are   */
  192.     /* included here. There are some tokens that one never expects!           */
  193.     case TK_NSEC: lr_err(TKPS,"Expecting '@*'."); break;
  194.     case TK_ONAM: lr_err(TKPS,"Expecting '@<'."); break;
  195.     case TK_ODEF